package com.ruoyi.common.utils.file;

import com.ruoyi.common.utils.StringUtils;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URL;

public class ImageCompressUtils {

    /**
     * 指定分辨率压缩图片
     *
     * @param srcPath 源图片地址
     * @param desPath 目标图片地址
     * @throws IOException
     */
    public static void compressPicForSize(String srcPath, String desPath) throws IOException {
        try {
            Thumbnails.of(srcPath)
                    //缩小图片
                    .size(500,500)
                    .toFile(desPath);
        }catch (IOException e) {
            System.out.println("-----读取图片发生异常:{}-----");
            System.out.println("-----尝试cmyk转化-----");
            File cmykJPEGFile = new File(srcPath);
            try {
                BufferedImage image = ImageIO.read(cmykJPEGFile);
                ImageOutputStream output = ImageIO.createImageOutputStream(cmykJPEGFile);
                if (!ImageIO.write(image, "jpg", output)) {
                    System.out.println("-----cmyk转化异常:{}-----");
                }
                Thumbnails.of(image).scale(0.4f).toFile(desPath);
                System.out.println();
            } catch (IOException e1) {
                System.out.println("-----cmyk转化异常:{}-----");
            }
        }
    }

    /**
     * 生成水印版图片
     * @param srcPath
     * @param desPath
     * @param rate  水印大小，0.35最佳
     * @param opacity 水印透明度，0.45最佳
     * @throws IOException
     */
    public static void addMarkerWater(String srcPath, String desPath, String position, Double rate, Float opacity) throws IOException {
        File file = new File(srcPath);
        BufferedImage originalImage = ImageIO.read(file);
        int width = (int) (originalImage.getWidth() * rate);
        int height = (int) (originalImage.getHeight() * rate);
        int size = Math.max(width, height);

        //读取水印图
        URL watermarkUrl = ImageCompressUtils.class.getResource("/static/watermarkFile.png");

        BufferedImage watermarkImage = Thumbnails.of(watermarkUrl).size(size, size).asBufferedImage();

        Positions positions = Positions.CENTER;;
        if ("CENTER".equals(position)){

        }else if ("TOP_LEFT".equals(position)){
            positions = Positions.TOP_LEFT;
        }else if ("TOP_CENTER".equals(position)){
            positions = Positions.TOP_CENTER;
        }else if ("TOP_RIGHT".equals(position)){
            positions = Positions.TOP_RIGHT;
        }else if ("CENTER_LEFT".equals(position)){
            positions = Positions.CENTER_LEFT;
        }else if ("CENTER_RIGHT".equals(position)){
            positions = Positions.CENTER_RIGHT;
        }else if ("BOTTOM_LEFT".equals(position)){
            positions = Positions.BOTTOM_LEFT;
        }else if ("BOTTOM_CENTER".equals(position)){
            positions = Positions.BOTTOM_CENTER;
        }else if ("BOTTOM_RIGHT".equals(position)){
            positions = Positions.BOTTOM_RIGHT;
        }
        Thumbnails.of(srcPath)
                //生成水印图
                .watermark(positions, watermarkImage, opacity)
                .scale(1)
                .toFile(desPath);
    }

     /**
     * 根据指定大小和指定精度压缩图片
     *
     * @param srcPath 源图片地址
     * @param desPath 目标图片地址
     * @param desFileSize 指定图片大小，单位kb
     * @param accuracy 精度，递归压缩的比率，建议小于0.9
     * @return desPath（目标图片地址）
     */
    public static String compressPicForScale(String srcPath, String desPath,
                                             long desFileSize, double accuracy) {
        if (StringUtils.isEmpty(srcPath) || StringUtils.isEmpty(srcPath)) {
            return null;
        }
        if (!new File(srcPath).exists()) {
            return null;
        }
        try {
            File srcFile = new File(srcPath);
            long srcFileSize = srcFile.length();
            System.out.println("源图片：" + srcPath + "，大小：" + srcFileSize / 1024 + "kb");

            // 1、先转换成jpg
            Thumbnails.of(srcPath).scale(1f).toFile(desPath);
            // 递归压缩，直到目标文件大小小于desFileSize
            compressPicCycle(desPath, desFileSize, accuracy);

            File desFile = new File(desPath);
            System.out.println("目标图片：" + desPath + "，大小" + desFile.length() / 1024 + "kb");
            System.out.println("图片压缩完成！");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return desPath;
    }

    private static void compressPicCycle(String desPath, long desFileSize,
                                         double accuracy) throws IOException {
        File srcFileJPG = new File(desPath);
        long srcFileSizeJPG = srcFileJPG.length();
        // 2、判断大小，如果小于500kb，不压缩；如果大于等于500kb，压缩
        if (srcFileSizeJPG <= desFileSize * 1024) {
            return;
        }
        // 计算宽高
        BufferedImage bim = ImageIO.read(srcFileJPG);
        int srcWidth = bim.getWidth();
        int srcHeight = bim.getHeight();
        int desWidth = new BigDecimal(srcWidth).multiply(new BigDecimal(accuracy)).intValue();
        int desHeight = new BigDecimal(srcHeight).multiply(new BigDecimal(accuracy)).intValue();

        Thumbnails.of(desPath)
                .size(desWidth, desHeight)
                .outputQuality(accuracy)
                .toFile(desPath);
        compressPicCycle(desPath, desFileSize, accuracy);
    }
}
